1. javapoet

https://github.com/square/javapoet

开源java代码生成框架,提供Java Api生成.java源文件。
可以很方便的使用它根据注解、数据库模式、协议格式等来对应生成代码。

使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
private void generateHelloworld() throws IOException{
MethodSpec main = MethodSpec.methodBuilder("main")
//main代表方法名
.addModifiers(Modifier.PUBLIC,Modifier.STATIC)
//Modifier 修饰的关键字
.addParameter(String[].class, "args")
//添加string[]类型的名为args的参数
.addStatement("$T.out.println($S)", System.class,"Hello World")
//添加代码,这里$T和$S后面会讲,这里其实就是添加了System,out.println("Hello World");
.build();
TypeSpec typeSpec = TypeSpec.classBuilder("HelloWorld")
//HelloWorld是类名
.addModifiers(Modifier.FINAL,Modifier.PUBLIC)
.addMethod(main)
//在类中添加方法
.build();
JavaFile javaFile = JavaFile.builder("com.example.helloworld", typeSpec)
.build();
javaFile.writeTo(System.out);
}

作者:尸情化异
链接:https://www.jianshu.com/p/95f12f72f69a
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

调用JavaPoet的API生成

1
2
3
4
5
6
7
package com.example.helloworld;

public final class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, JavaPoet!");
}
}

2. RGen元模型生成器

Ruby Modelling and Generator Framework

Documentation
介绍

此处输入图片的描述

对象用来表示模型元素,类用来表示元模型元素。

RGen生成器模板

此处输入图片的描述

状态机生成器模板例子

它用来产生一个为每个复合状态创建的C++抽象类的头文件。跟随着状态模式和,能够从这个类得到每个子状态的状态类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<% define 'Header', :for => CompositeState do %>         # (1)
<% file abstractSubstateClassName+".h" do %>

<% expand '/Util::IfdefHeader', abstractSubstateClassName %> # (2)
class <%= stateClassName %>;
<%nl%>

class <%= abstractSubstateClassName %> # (3)
{
public:<%iinc%> # (4)
<%=abstractSubstateClassName%>(<%=stateClassName%> &cont, char* name);
virtual ~<%= abstractSubstateClassName %>() {};
<%nl%>

<%= stateClassName %> &getContext() {<%iinc%>
return fContext;<%idec%>

}
<%nl%>
char *getName() { return fName; };
<%nl%>
virtual void entryAction() {};
virtual void exitAction() {};
<%nl%>

<% for t in (outgoingTransitions + allSubstateTransitions).trigger %> # (5)
virtual void <%= t %>() {};
<% end %>

<%nl%><%idec%>
private:<%iinc%>
char* fName;
<%= stateClassName %> &fContext;<%idec%>

};
<% expand '/Util::IfdefFooter', abstractSubstateClassName %>
<% end %>

<% end %>

输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// Listing 11: Example C++ output file "AbstractOperatingSubstate.h"

#ifndef ABSTRACTOPERATINGSUBSTATE_H_
#define ABSTRACTOPERATINGSUBSTATE_H_

class OperatingState;

class AbstractOperatingSubstate
{
public:
AbstractOperatingSubstate(OperatingState &context, char* name);
virtual ~AbstractOperatingSubstate() {};

OperatingState &getContext() {
return fContext;
}

char *getName() { return fName; };

virtual void entryAction() {};
virtual void exitAction() {};

virtual void powerBut() {};
virtual void modeBut() {};


private:
char* fName;
OperatingState &fContext;
};

#endif /* ABSTRACTOPERATINGSUBSTATE_H_ */

3. Jet Model Robotization

Jmr使用Jet模板生成代码。Jet是Eclipse开源的模板引擎

Java Emitter Templates

随着模型驱动开发(MDD)的发展而普及开来。Eclipse 项目有一个称为 JET 的技术项目就是一个专门的代码生成器。

参数 + 蓝图 = 所需的工件

使用 JET 在 Eclipse 中创建更多更好的代码

属性模板
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class <c:get select="/app/@class" /> {
<c:iterate select="/app/property" var="p" >
private <c:get select="$p/@type" /> <c:get select="$p/@name" />;
</c:iterate>

public <c:get select="/app/@class" />() {
<c:iterate select="/app/property" var="p" >
this.<c:get select="$p/@name" /> = <c:choose select="$p/@type" >
<c:when test="'String'">"<c:get select="$p/@initial" />"</c:when>
<c:otherwise><c:get select="$p/@initial" /></c:otherwise>
</c:choose>
;
</c:iterate>
}

<c:iterate select="/app/property" var="p" >
public void set<c:get select=\
"camelCase($p/@name)" />(<c:get select="$p/@type" />
<c:get select="$p/@name" />) {
System.out.println\
("In set<c:get select=\
"camelCase($p/@name)" />()");
this.<c:get select="$p/@name" /> = <c:get select="$p/@name" />;
}

public <c:get select=\
"$p/@type" /> get<c:get select="camelCase($p/@name)" />() {
System.out.println("In get<c:get select="camelCase($p/@name)" />()");
return <c:get select="$p/@name" />;
}

</c:iterate>
}
输入参数
1
2
3
4
5
<app class="Car">
<property name="model" type="String" initial="Honda Accord" />
<property name="horsepower" type="int" initial="140" />
<property name="spareTires" type="boolean" initial="true" />
</app>
生成的类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
class Car {
private String model;
private int horsepower;
private boolean spareTires;

public Car() {
this.model = "Honda Accord";
this.horsepower = 140;
this.spareTires = true;
}

public void setModel(String model) {
System.out.println("In setModel()");
this.model = model;
}

public String getModel() {
System.out.println("In getModel()");
return model;
}

public void setHorsepower(int horsepower) {
System.out.println("In setHorsepower()");
this.horsepower = horsepower;
}

public int getHorsepower() {
System.out.println("In getHorsepower()");
return horsepower;
}

public void setSparetires(boolean spareTires) {
System.out.println("In setSparetires()");
this.spareTires = spareTires;
}

public boolean getSparetires() {
System.out.println("In getSparetires()");
return spareTires;
}

}

4. AutoValue

“AutoValue is a great tool for eliminating the drudgery of writing mundane value classes in Java. It encapsulates much of the advice in Effective Java Chapter 2, and frees you to concentrate on the more interesting aspects of your program. The resulting program is likely to be shorter, clearer, and freer of bugs. Two thumbs up.”

AutoValue的是Google为了实现ValueClass设计的自动编译框架。

userguide

An Introduction to AutoValue

使用

1
2
3
dependencies {
apt 'com.google.auto.value:auto-value:1.2'
}
1
2
3
4
5
6
7
8
@AutoValue
public abstract class Story{
public abstract int id();
public abstract String title();
public static Story create(int id, String title){
new AutoValue_Story(id,title);
}
}

输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public class Story{
private int id;
private String title;

public Story(int id, String title){
this.id = id;
this.title = title;
}

public int id(){
return this.id;
}

public int title(){
return this.title;
}

@Override
public String toString(){
return id + title;
}

@Override
public int hashCode() {
int hash = 7;
hash = 31 * hash + this.id;
hash = 31 * hash + (null == title ? 0 : title.hashCode());
return hash;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || !(o instanceof Stroy)) return false;
Story s = (Story) o;
if (s.id != s.id) return false;
return s.title.equals(s.title);
}
}

5. Ruby 代码生成器

使用 Ruby 开发代码生成器

Class: ERB

ERB 是 Ruby 标准库的成员。

ERB 中使用<% %>在模板文件中嵌入 Ruby 代码,<% %> 中的 Ruby 代码用于指定代码生成中数据模型相关的信息,模板中的文本给出了模型无关的信息。<% %> 中用于给出一段 Ruby 代码, <%= %> 表示表达式求值的结果将被输出出来。

此处输入图片的描述

ERB模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/*
* 项目名称:<%=projectName%>
*
* 创建日期 : <%=date%>
*
* 1.0.0 版 (<%=bean.author%>)
*/
package com.<%=projectPackage%>.<%=bean.package%>.domain;
<%if(bean.hasDateType())%>import java.util.Date;<%end%>

public class <%=bean.domain%>Domain {
<% bean.properties.each do |p|%>
/** <%=p.desc%> */
private <%=p.getJavaType()%> <%=p.field%>;
<%end%>
<% bean.properties.each do |p|%>
/**
* 获取 <%=(p.desc)%>
*/
public <%=p.getJavaType()%> get<%=p.upcaseField()%>(){
return this.<%=p.field%>;
}
/**
* 设置 <%=(p.desc)%>
*/
public void set<%=p.upcaseField()%>(<%=p.getJavaType()%> <%=p.field%>){
this.<%=p.field%> = <%=p.field%>;
}
<%end%>
}

使用 USER 数据模型作为输入,调用上述模板,得到的输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
/*
* 项目名称:XX 系统
*
* 创建日期 : 2011-12-08
*
* 1.0.0 版 (gaoshang)
*/
package com.test.example.domain;


public class UserDomain {
/** ID */
private Integer id;
/** 姓名 */
private String name;
/** 身份证号 */
private String idcard;
/** 地址 */
private String address;
/**
* 获取 ID
*/
public Integer getId(){
return this.id;
}
/**
* 设置 ID
*/
public void setId(Integer id){
this.id = id;
}
/**
* 获取 姓名
*/
public String getName(){
return this.name;
}
/**
* 设置 姓名
*/
public void setName(String name){
this.name = name;
}
/**
* 获取 身份证号
*/
public String getIdcard(){
return this.idcard;
}
/**
* 设置 身份证号
*/
public void setIdcard(String idcard){
this.idcard = idcard;
}
/**
* 获取 地址
*/
public String getAddress(){
return this.address;
}
/**
* 设置 地址
*/
public void setAddress(String address){
this.address = address;
}
}

6. CodeSmith

官网

CodeSmith 是一种基于模板的代码生成工具,它使用类似于 ASP.NET的语法来生成任意类型的代码或文本。

此处输入图片的描述

编写第一个代码模板

7. Velocity

Velocity是一个基于Java的模板引擎。它允许任何人使用简单而强大的模板语言来引用Java代码中定义的对象。

Velocity的功能远远超出了网络的范围; 例如,它可以用于从模板生成SQL,PostScript和XML。它可以用作生成源代码和报告的独立实用程序,也可以用作其他系统的集成组件。例如,Velocity为各种Web框架提供模板服务,使他们能够根据真正的MVC模型,使视图引擎促进Web应用程序的开发。

User Guide

使用 Velocity 模板引擎快速生成代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// HelloVelocity.java
public class HelloVelocity {
public static void main(String[] args) {
VelocityEngine ve = new VelocityEngine();
ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath");
ve.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());

ve.init();

Template t = ve.getTemplate("hellovelocity.vm");
VelocityContext ctx = new VelocityContext();

ctx.put("name", "velocity");
ctx.put("date", (new Date()).toString());

List temp = new ArrayList();
temp.add("1");
temp.add("2");
ctx.put("list", temp);

StringWriter sw = new StringWriter();

t.merge(ctx, sw);

System.out.println(sw.toString());
}
}

在 HelloVelocity 的代码中,首先 new 了一个 VelocityEngine 类,这个类设置了 Velocity 使用的一些配置,在初始化引擎之后就可以读取 hellovelocity.vm 这个模板生成的 Template 这个类。之后的 VelocityContext 类是配置 Velocity 模板读取的内容。这个 context 可以存入任意类型的对象或者变量,让 template 来读取。这个操作就像是在使用 JSP 开发时,往 request 里面放入 key-value,让 JSP 读取一样。

接下来就是写 hellovelocity.vm 文件了,这个文件实际定义了 Velocity 的输出内容和格式。

1
2
3
4
5
6
7
8
//Hellovelocity.vm
#set( $iAmVariable = "good!" )
Welcome $name to velocity.com
today is $date.
#foreach ($i in $list)
$i
#end
$iAmVariable

输出

1
2
3
4
5
Welcome velocity to velocity.com
today is Sun Mar 23 19:19:04 CST 2014.
1
2
good!

8. StringTemplate

http://www.stringtemplate.org/

模板

1
2
3
4
5
sqlTemplate(columns,condition)
::= <<select <columns;separator=",">
from table
where 1=1 <if(condition)>and <condition><endif>
>>

JAVA调用

1
2
3
4
5
6
7
8
9
10
STGroup stg = new STGroupFile("dataExtractSql.stg");
ST sqlST = stg.getInstanceOf("sqlTemplate");

List<String> columnList = new LinkedList<String>();
columnList.add("order_id");
columnList.add("price");
columnList.add("phone");
sqlST.add("columns", columnList);
sqlST.add("condition", "dt='2017-04-04'");
System.out.print(sqlST.render());

输出

1
2
3
select order_id,price,phone
from table
where 1=1 and dt='2017-04-04'

9. FreeMarker

FreeMarker 是一款 模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页,电子邮件,配置文件,源代码等)的通用工具。 它不是面向最终用户的,而是一个Java类库,是一款程序员可以嵌入他们所开发产品的组件。

此处输入图片的描述

官网

http://try.freemarker.org/

10. mustache

mustache.java

语法